package com.blog.service.service;

import com.blog.check.check.BlogCheck;
import com.blog.check.check.CheckResult;
import com.blog.check.result.Result;
import com.blog.check.resultenum.BlogChkRsEnum;
import com.blog.dao.domain.BlogDO;
import com.blog.dao.domain.BlogTypeDO;
import com.blog.dao.domain.ViewsDO;
import com.blog.dao.query.BlogQuery;
import com.blog.dao.query.CommentQuery;
import com.blog.dao.query.ViewsQuery;
import com.blog.exception.ServiceException;
import com.blog.form.BlogForm;

import com.blog.service.constant.SysPropertiesKeyConsts;
import com.blog.service.dto.BlogDTO;
import com.blog.until.BeanCopierUtil;
import com.blog.until.PrimaryKeyUtil;
import com.blog.until.RandomUtil;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import lombok.SneakyThrows;


import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Base64Utils;

import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.util.*;


/**
 * 博客服务
 *
 * @author 泡面ing
 * @date 2021/11/24
 */
@Service
public class BlogService extends BaseService{

    private BlogCheck blogCheck;
    private CommentService commentService;

    @Autowired
    public void setBlogCheck(BlogCheck blogCheck){
        this.blogCheck = blogCheck;
    }
    @Autowired
    public void setCommentService(CommentService commentService){
        this.commentService = commentService;
    }


    Properties properties;
    {
        try {
            properties = getProperties(SYS_PROPERTIES_FILEPATH);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @SneakyThrows
    private String photoSavePath(String location){
        String photoPath = properties.getProperty(SysPropertiesKeyConsts.PHOTO_PATH);
        Date time = getTime();
        if (StringUtils.isBlank(photoPath)){
            logger.error(SysPropertiesKeyConsts.ICON_PATH + "is blank");
            throw new Exception(SysPropertiesKeyConsts.ICON_PATH + "is blank");
        }
        String base64Prefix = StringUtils.substringBefore(location, ",");
        String suffix = getImageSuffix(base64Prefix);

        return photoPath + "/" + RandomUtil.getRandomCharAndNum(6) + "_"
                + DateFormatUtils.format(time, "yyyyMMddHHmmss") + suffix;

    }

    @SneakyThrows
    private String blogSavePath(){
        Date time = getTime();
        String blogPath = properties.getProperty(SysPropertiesKeyConsts.BLOG_PATH);
        if (StringUtils.isBlank(blogPath)){
            logger.error(SysPropertiesKeyConsts.BLOG_PATH + " is blank。");
            throw new Exception(SysPropertiesKeyConsts.BLOG_PATH + " is blank。");
        }
        return blogPath + "/" + RandomUtil.getRandomCharAndNum(6) + "_"
                + DateFormatUtils.format(time, "yyyyMMddHHmmss") + ".txt";

    }


    @Transactional(rollbackFor = Exception.class)
    public Result list(int pageNum,int pageSize, BlogQuery blogQuery){

        try{
            List<BlogDTO> blogDTOList = new ArrayList<>();
            List<BlogDO> blogDOList = blogDAO.list(blogQuery);
            if (blogDOList.size() == 0){
                return Result.success(blogDTOList);
            }
            for (BlogDO blogDO : blogDOList){
                BlogDTO blogDTO = getShowDTO(blogDO, null,null);
                blogDTOList.add(blogDTO);
            }
            PageHelper.startPage(pageNum,pageSize);
            PageInfo<BlogDTO> blogDTOPageInfo = new PageInfo<>(blogDTOList);
            return Result.success(blogDTOPageInfo);
        }catch (Exception e){
            throw new ServiceException(e);
        }

    }
    @SneakyThrows
    private BlogDTO getShowDTO(BlogDO blogDO,String content,Object comment){

        BlogDTO blogDTO = new BlogDTO();
        BlogTypeDO blogTypeDO = blogTypeDAO.get(blogDO.getTypeId());

        String blogType = blogTypeDO.getTypeName();

        File photoLocationFile = new File(blogDO.getPhotoLocation());
        if (photoLocationFile.exists()){
            byte[] bytes = FileUtils.readFileToByteArray(photoLocationFile);
            String photo = getImageBase64Prefix(photoLocationFile) + "," +Base64Utils.encodeToString(bytes);
            blogDTO.setPhotoLocation(photo);
        }

        blogDTO.setId(blogDO.getId());
        blogDTO.setTitle(blogDO.getTitle());
        blogDTO.setSummary(blogDO.getSummary());
        blogDTO.setReleaseDate(blogDO.getReleaseDate());
        blogDTO.setClickHit(blogDO.getClickHit());
        blogDTO.setReplyHit(blogDO.getReplyHit());
        blogDTO.setBlogType(blogType);
        blogDTO.setKeyWord(blogDO.getKeyWord());
        blogDTO.setContent(content);
        blogDTO.setComment(comment);
        return blogDTO;
    }
    @Transactional(rollbackFor = Exception.class)
    @SneakyThrows
    public Result get(String id,HttpServletRequest request){

        CheckResult checkResult = blogCheck.checkGet(id);
        if (checkResult.getCode() != BlogChkRsEnum.SUCCESS.getCode()){
            logger.error(logInfo(checkResult));
            return Result.failure(checkResult);
        }

        BlogDTO blogDTO;
        BlogDO blogDO = blogDAO.get(id);
        //获取ip
        String ip = getIpAddress(request);
        ViewsQuery viewsQuery = new ViewsQuery();
        viewsQuery.setArticle(id);
        viewsQuery.setIp(ip);
        List<ViewsDO> viewsDOList = viewsDAO.list(viewsQuery);
        if (viewsDOList.size()<1){
            ViewsDO viewsDO = new ViewsDO();
            viewsDO.setArticle(id);
            viewsDO.setIp(ip);
            viewsDAO.save(viewsDO);
            blogDO.setClickHit(blogDO.getClickHit()+1);
            blogDAO.update(blogDO);
        }
        String content = null;
        File blogFile = new File(blogDO.getContent());
        if (blogFile.exists()){
             content = FileUtils.readFileToString(blogFile ,"utf-8");
        }
        CommentQuery commentQuery = new CommentQuery();
        commentQuery.setId(id);
        blogDTO = getShowDTO(blogDO,content,commentService.list(commentQuery));
        return Result.success(blogDTO);
    }

    @Transactional(rollbackFor = Exception.class)
    public Result save(BlogForm blogForm){
        try {

            CheckResult checkResult = blogCheck.checkSave(blogForm);
            if (checkResult.getCode() != BlogChkRsEnum.SUCCESS.getCode()){
                logger.error(logInfo(checkResult));
                return Result.failure(checkResult);
            }

            String destPhotoPath = photoSavePath(blogForm.getPhotoLocation());
            String destBlogPath = blogSavePath();
            BlogDO blogDO = buildSaveBlog(blogForm,destBlogPath,destPhotoPath);
            blogDAO.save(blogDO);

            String icon = StringUtils.substringAfter(blogForm.getPhotoLocation(), ",");
            byte[] bytes = Base64Utils.decodeFromString(icon);

            FileUtils.writeByteArrayToFile(new File(destPhotoPath), bytes);
            FileUtils.writeStringToFile(new File(destBlogPath), blogForm.getContent(), "utf-8", true);
            return Result.success();
        }catch (Exception e){
            throw new ServiceException(e);
        }
    }
    @SneakyThrows
    private BlogDO buildSaveBlog(BlogForm blogForm,String destBlogPath,String destPhotoPath) {
        Date time = getTime();
        BlogDO blogDO = BeanCopierUtil.create(blogForm,BlogDO.class);
        String blogId = PrimaryKeyUtil.get();
        blogDO.setId(blogId);
        blogDO.setTitle(blogForm.getTitle());

        if(blogForm.getContent().length() > 100){
            blogDO.setSummary(blogForm.getContent().substring(0,100) + "......");
        }else{
            blogDO.setSummary(blogForm.getContent());
        }
        blogDO.setReleaseDate(time);
        blogDO.setClickHit(0);
        blogDO.setReplyHit(0);
        blogDO.setTypeId(blogForm.getTypeId());
        blogDO.setContent(destBlogPath);
        blogDO.setKeyWord(getUsername());
        blogDO.setPhotoLocation(destPhotoPath);
        return blogDO;
    }
    @Transactional(rollbackFor = Exception.class)
    public Result update(BlogForm blogForm,String blogId){
        try{

            CheckResult checkResult = blogCheck.checkUpdate(blogId);
            if (checkResult.getCode() != BlogChkRsEnum.SUCCESS.getCode()){
                logger.error(logInfo(checkResult));
                return Result.failure(checkResult);
            }

            String destPhotoPath = photoSavePath(blogForm.getPhotoLocation());
            BlogDO blogDO = buildUpdateBlog(blogId,blogForm,destPhotoPath);
            blogDAO.update(blogDO);

            if (StringUtils.isNotBlank(blogForm.getPhotoLocation())){

                String icon = StringUtils.substringAfter(blogForm.getPhotoLocation(), ",");
                byte[] bytes = Base64Utils.decodeFromString(icon);

                FileUtils.writeByteArrayToFile(new File(destPhotoPath), bytes);
            }

            if (StringUtils.isNotBlank(blogForm.getContent())){
                FileUtils.writeStringToFile(new File(blogDO.getContent()), blogForm.getContent(), "utf-8", true);
            }
            return Result.success();
        }catch (Exception e){
            throw new ServiceException(e);
        }
    }
    @SneakyThrows
    private BlogDO buildUpdateBlog(String blogId, BlogForm blogForm,String destPhotoPath) {
        BlogDO blogDO = blogDAO.get(blogId);
        BlogDO newBlogDO = BeanCopierUtil.create(blogDO,BlogDO.class);
        if (StringUtils.isNotBlank(blogForm.getTitle())){
            newBlogDO.setTitle(blogForm.getTitle());
        }
        if (StringUtils.isNotBlank(blogForm.getContent())){
            FileUtils.deleteQuietly(new File(blogDO.getContent()));
            if(blogForm.getContent().length() > 100){
                newBlogDO.setSummary(blogForm.getContent().substring(0,100) + "......");
            }else{
                newBlogDO.setSummary(blogForm.getContent());
            }
        }
        if (StringUtils.isNotBlank(blogForm.getTypeId())){
            newBlogDO.setTypeId(blogForm.getTypeId());
        }
        if (StringUtils.isNotBlank(blogForm.getPhotoLocation())){
            FileUtils.deleteQuietly(new File(blogDO.getPhotoLocation()));
            newBlogDO.setPhotoLocation(destPhotoPath);
        }
        return newBlogDO;
    }

    @Transactional(rollbackFor = Exception.class)
    public Result remove(String blogId){
        try{

            CheckResult checkResult = blogCheck.checkRemove(blogId);
            if (checkResult.getCode() != BlogChkRsEnum.SUCCESS.getCode()){
                logger.error(logInfo(checkResult));
                return Result.failure(checkResult);
            }

            viewsDAO.remove(blogId);

            BlogDO blogDO = blogDAO.get(blogId);
            FileUtils.deleteQuietly(new File(blogDO.getContent()));
            FileUtils.deleteQuietly(new File(blogDO.getPhotoLocation()));
            commentDAO.deleteAll(blogId);
            blogDAO.remove(blogId);
            return Result.success();
        }catch (Exception e){
            throw new ServiceException(e);
        }
    }

}
